#!/bin/bash
# Azure Setup Script
# 19-04-2021

trap "exit" INT
aks_Exists=""
cleanup () {
  # Make super duper sure we reap all the spinners
  if [ ! -z "$allpids" ]; then
    for pid in $allpids; do
      kill "$pid" 1>/dev/null 2>&1
    done
    tput sgr0
  fi
  tput cnorm
  return 1
}
# This tries to catch any exit, whether normal or forced (e.g. Ctrl-C)
trap cleanup INT QUIT TERM EXIT

# scolors - Color constants

# do we have tput?
if which 'tput' > /dev/null; then
  # do we have a terminal?
  if [ -t 1 ]; then
    # does the terminal have colors?
    ncolors=$(tput colors)
    if [ "$ncolors" -ge 8 ]; then
      RED=$(tput setaf 1)
      GREEN=$(tput setaf 2)
      YELLOW=$(tput setaf 3)
      BLUE=$(tput setaf 4)
      MAGENTA=$(tput setaf 5)
      CYAN=$(tput setaf 6)
      WHITE=$(tput setaf 7)
      REDBG=$(tput setab 1)
      GREENBG=$(tput setab 2)
      YELLOWBG=$(tput setab 3)
      BLUEBG=$(tput setab 4)
      MAGENTABG=$(tput setab 5)
      CYANBG=$(tput setab 6)
      WHITEBG=$(tput setab 7)

      BOLD=$(tput bold)
      UNDERLINE=$(tput smul) # Many terminals don't support this
      NORMAL=$(tput sgr0)
    fi
  fi
else
  echo "tput not found, colorized output disabled."
  RED=''
  GREEN=''
  YELLOW=''
  BLUE=''
  MAGENTA=''
  CYAN=''
  WHITE=''
  REDBG=''
  GREENBG=''
  YELLOWBG=''
  BLUEBG=''
  MAGENTABG=''
  CYANBG=''

  BOLD=''
  UNDERLINE=''
  NORMAL=''
fi

# LOG_PATH - Define $LOG_PATH in your script to log to a file, otherwise
# just writes to STDOUT.

# LOG_LEVEL_STDOUT - Define to determine above which level goes to STDOUT.
# By default, all log levels will be written to STDOUT.
LOG_LEVEL_STDOUT="INFO"

# LOG_LEVEL_LOG - Define to determine which level goes to LOG_PATH.
# By default all log levels will be written to LOG_PATH.
LOG_LEVEL_LOG="INFO"

# Useful global variables that users may wish to reference
SCRIPT_ARGS="$*"
SCRIPT_NAME="$0"
SCRIPT_NAME="${SCRIPT_NAME#\./}"
SCRIPT_NAME="${SCRIPT_NAME##/*/}"

# Determines if we print colors or not
if [ "$(tty -s)" ]; then
    INTERACTIVE_MODE="off"
else
    INTERACTIVE_MODE="on"
fi

#--------------------------------------------------------------------------------------------------
# Begin Logging Section
if [ "${INTERACTIVE_MODE}" = "off" ]
then
    # Then we don't care about log colors
    LOG_DEFAULT_COLOR=""
    LOG_ERROR_COLOR=""
    LOG_INFO_COLOR=""
    LOG_SUCCESS_COLOR=""
    LOG_WARN_COLOR=""
    LOG_DEBUG_COLOR=""
else
    LOG_DEFAULT_COLOR=$(tput sgr0)
    LOG_ERROR_COLOR=$(tput setaf 1)
    LOG_INFO_COLOR=$(tput setaf 6)
    LOG_SUCCESS_COLOR=$(tput setaf 2)
    LOG_WARN_COLOR=$(tput setaf 3)
    LOG_DEBUG_COLOR=$(tput setaf 4)
fi

# This function scrubs the output of any control characters used in colorized output
# It's designed to be piped through with text that needs scrubbing.  The scrubbed
# text will come out the other side!
prepare_log_for_nonterminal() {
    # Essentially this strips all the control characters for log colors
    sed "s/[[:cntrl:]]\\[[0-9;]*m//g"
}

log() {
  local log_text="$1"
  local log_level="$2"
  local log_color="$3"

  # Levels for comparing against LOG_LEVEL_STDOUT and LOG_LEVEL_LOG
  local LOG_LEVEL_DEBUG=0
  local LOG_LEVEL_INFO=1
  local LOG_LEVEL_SUCCESS=2
  local LOG_LEVEL_WARNING=3
  local LOG_LEVEL_ERROR=4

  # Default level to "info"
  [ -z "${log_level}" ] && log_level="INFO";
  [ -z "${log_color}" ] && log_color="${LOG_INFO_COLOR}";

  # Validate LOG_LEVEL_STDOUT and LOG_LEVEL_LOG since they'll be eval-ed.
  case $LOG_LEVEL_STDOUT in
    DEBUG|INFO|SUCCESS|WARNING|ERROR)
      ;;
    *)
      LOG_LEVEL_STDOUT=INFO
      ;;
  esac
  case $LOG_LEVEL_LOG in
    DEBUG|INFO|SUCCESS|WARNING|ERROR)
      ;;
    *)
      LOG_LEVEL_LOG=INFO
      ;;
  esac

  # Check LOG_LEVEL_STDOUT to see if this level of entry goes to STDOUT.
  # XXX This is the horror that happens when your language doesn't have a hash data struct.
  eval log_level_int="\$LOG_LEVEL_${log_level}";
  eval log_level_stdout="\$LOG_LEVEL_${LOG_LEVEL_STDOUT}"
  # shellcheck disable=SC2154
  if [ "$log_level_stdout" -le "$log_level_int" ]; then
    # STDOUT
    printf "%s[%s]%s %s\\n" "$log_color" "$log_level" "$LOG_DEFAULT_COLOR" "$log_text";
  fi
  # This is all very tricky; figures out a numeric value to compare.
  eval log_level_log="\$LOG_LEVEL_${LOG_LEVEL_LOG}"
  # Check LOG_LEVEL_LOG to see if this level of entry goes to LOG_PATH
  # shellcheck disable=SC2154
  if [ "$log_level_log" -le "$log_level_int" ]; then
    # LOG_PATH minus fancypants colors
    if [ ! -z "$LOG_PATH" ]; then
      today=$(date +"%Y-%m-%d %H:%M:%S %Z")
      printf "[%s] [%s] %s\\n" "$today" "$log_level" "$log_text" >> "$LOG_PATH"
    fi
  fi

  return 0;
}

log_info()      { log "$@"; }
log_success()   { log "$1" "SUCCESS" "${LOG_SUCCESS_COLOR}"; }
log_error()     { log "$1" "ERROR" "${LOG_ERROR_COLOR}"; }
log_warning()   { log "$1" "WARNING" "${LOG_WARN_COLOR}"; }
log_debug()     { log "$1" "DEBUG" "${LOG_DEBUG_COLOR}"; }

# End Logging Section
#--------------------------------------------------------------------------------------------------


# Config variables, set these after sourcing to change behavior.
SPINNER_COLORNUM=2 # What color? Irrelevent if COLORCYCLE=1.
SPINNER_COLORCYCLE=1 # Does the color cycle?
SPINNER_DONEFILE="stopspinning" # Path/name of file to exit on.
SPINNER_SYMBOLS="ASCII_PROPELLER" # Name of the variable containing the symbols.
SPINNER_CLEAR=1 # Blank the line when done.

spinner () {
  # Safest option are one of these. Doesn't need Unicode, at all.
  local ASCII_PROPELLER="/ - \\ |"

  # Bigger spinners and progress type bars; takes more space.
  local WIDE_ASCII_PROG="[>----] [=>---] [==>--] [===>-] [====>] [----<] [---<=] [--<==] [-<===] [<====]"
  local WIDE_UNI_GREYSCALE="▒▒▒▒▒▒▒ █▒▒▒▒▒▒ ██▒▒▒▒▒ ███▒▒▒▒ ████▒▒▒ █████▒▒ ██████▒ ███████ ██████▒ █████▒▒ ████▒▒▒ ███▒▒▒▒ ██▒▒▒▒▒ █▒▒▒▒▒▒ ▒▒▒▒▒▒▒"
  local WIDE_UNI_GREYSCALE2="▒▒▒▒▒▒▒ █▒▒▒▒▒▒ ██▒▒▒▒▒ ███▒▒▒▒ ████▒▒▒ █████▒▒ ██████▒ ███████ ▒██████ ▒▒█████ ▒▒▒████ ▒▒▒▒███ ▒▒▒▒▒██ ▒▒▒▒▒▒█"

  local SPINNER_NORMAL
  SPINNER_NORMAL=$(tput sgr0)

  eval SYMBOLS=\$${SPINNER_SYMBOLS}

  # Get the parent PID
  SPINNER_PPID=$(echo $PPID)
  while :; do
    tput civis
    for c in ${SYMBOLS}; do
      if [ $SPINNER_COLORCYCLE -eq 1 ]; then
        if [ $SPINNER_COLORNUM -eq 7 ]; then
          SPINNER_COLORNUM=1
        else
          SPINNER_COLORNUM=$((SPINNER_COLORNUM+1))
        fi
      fi
      local SPINNER_COLOR
      SPINNER_COLOR=$(tput setaf ${SPINNER_COLORNUM})
      tput sc
      env printf "${SPINNER_COLOR}${c}${SPINNER_NORMAL}"
      tput rc
      if [ -f "${SPINNER_DONEFILE}" ]; then
        if [ ${SPINNER_CLEAR} -eq 1 ]; then
          tput el
        fi
	      rm -f ${SPINNER_DONEFILE}
	      break 2
      fi
      # This is questionable. sleep with fractional seconds is not
      # always available, but seems to not break things, when not.
      env sleep .2
      # Check to be sure parent is still going; handles sighup/kill
      if [ ! -z "$SPINNER_PPID" ]; then
        # This is ridiculous. ps prepends a space in the ppid call, which breaks
        # this ps with a "garbage option" error.
        # XXX Potential gotcha if ps produces weird output.
        # shellcheck disable=SC2086
        SPINNER_PARENTUP=$(ps $SPINNER_PPID | tail -n +2)
        if [ -z "$SPINNER_PARENTUP" ]; then
          break 2
        fi
      fi
    done
  done
  tput rc
  tput cnorm
  return 0
}

# run_ok - function to run a command or function, start a spinner and print a confirmation
# indicator when done.
timestamp=$(date +"%Y%m%dT%H%M")
touch /tmp/run-$timestamp.log
RUN_LOG="/tmp/run-$timestamp.log"

# Check for unicode support in the shell
# This is a weird function, but seems to work. Checks to see if a unicode char can be
# written to a file and can be read back.
shell_has_unicode () {
  # Write a unicode character to a file...read it back and see if it's handled right.
  env printf "\\u2714"> unitest.txt

  read -r unitest < unitest.txt
  rm -f unitest.txt
  if [ ${#unitest} -le 3 ]; then
    return 0
  else
    return 1
  fi
}

# Setup spinner with our prefs.
SPINNER_COLORCYCLE=0
SPINNER_COLORNUM=6
if shell_has_unicode; then
  SPINNER_SYMBOLS="WIDE_UNI_GREYSCALE2"
else
  SPINNER_SYMBOLS="WIDE_ASCII_PROG"
fi
SPINNER_CLEAR=0 # Don't blank the line, so our check/x can simply overwrite it.

# Perform an action, log it, and print a colorful checkmark or X if failed
# Returns 0 if successful, $? if failed.
run_ok () {
  # Shell is really clumsy with passing strings around.
  # This passes the unexpanded $1 and $2, so subsequent users get the
  # whole thing.
  local cmd="${1}"
  local msg="${2}"
  local columns
  columns=$(tput cols)
  if [ "$columns" -ge 80 ]; then
    columns=79
  fi
  # shellcheck disable=SC2004
  COL=$((${columns}-${#msg}-7 ))

  printf "%s%${COL}s" "$2"
  # Make sure there some unicode action in the shell; there's no
  # way to check the terminal in a POSIX-compliant way, but terms
  # are mostly ahead of shells.
  # Unicode checkmark and x mark for run_ok function
  CHECK='\u2714'
  BALLOT_X='\u2718'
  spinner &
  spinpid=$!
  allpids="$allpids $spinpid"
  echo "Spin pid is: $spinpid" >> ${RUN_LOG}
  eval "${cmd}" 1>> ${RUN_LOG} 2>&1
  local res=$?
  touch ${SPINNER_DONEFILE}
  env sleep .2 # It's possible to have a race for stdout and spinner clobbering the next bit
  # Just in case the spinner survived somehow, kill it.
  pidcheck=$(ps ${spinpid} | tail -n +2)
  if [ ! -z "$pidcheck" ]; then
    echo "Made it here...why?" >> ${RUN_LOG}
    kill $spinpid 2>/dev/null
    rm -rf ${SPINNER_DONEFILE} 2>/dev/null 2>&1
    tput rc
    tput cnorm
  fi
  # Log what we were supposed to be running
  printf "${msg}: " >> ${RUN_LOG}
  if shell_has_unicode; then
    if [ $res -eq 0 ]; then
      printf "Success.\\n" >> ${RUN_LOG}
      env printf "${GREENBG}[  ${CHECK}  ]${NORMAL}\\n"
      return 0
    else
      log_error "Failed with error: ${res}"
      env printf "${REDBG}[  ${BALLOT_X}  ]${NORMAL}\\n"
      if [ "$RUN_ERRORS_FATAL" ]; then
        echo
        log_fatal "Something went wrong. Exiting."
        log_fatal "The last few log entries were:"
        tail -15 ${RUN_LOG}
        exit 1
      fi
      return ${res}
    fi
  else
    if [ $res -eq 0 ]; then
      printf "Success.\\n" >> ${RUN_LOG}
      env printf "${GREENBG}[ OK! ]${NORMAL}\\n"
      return 0
    else
      printf "Failed with error: ${res}\\n" >> ${RUN_LOG}
      echo
      env printf "${REDBG}[ERROR]${NORMAL}\\n"
      if [ "$RUN_ERRORS_FATAL" ]; then
        log_fatal "Something went wrong with the previous command. Exiting."
        exit 1
      fi
      return ${res}
    fi
  fi
}

version=1.1.0
# Temporary colors
RED="$(tput setaf 1)"
YELLOW="$(tput setaf 3)"
CYAN="$(tput setaf 6)"
NORMAL="$(tput sgr0)"

banner=false
touch /tmp/was-azure-setup-$timestamp.log
log="/tmp/was-azure-setup-$timestamp.log"
LOG_PATH="$log"
# Setup run_ok
# shellcheck disable=SC2034
RUN_LOG="$log"
# Exit on any failure during shell stage
# shellcheck disable=SC2034
RUN_ERRORS_FATAL=1

# Console output level; ignore debug level messages.
if [ "$VERBOSE" = "1" ]; then
  # shellcheck disable=SC2034
  LOG_LEVEL_STDOUT="DEBUG"
else
  # shellcheck disable=SC2034
  LOG_LEVEL_STDOUT="INFO"
fi
# Log file output level; catch literally everything.
# shellcheck disable=SC2034
LOG_LEVEL_LOG="DEBUG"

# log_fatal calls log_error
log_fatal() {
  log_error "$1"
}

success () {
  log_success "$1 Succeeded."
}


install_msg() {

cat <<EOF


  Welcome to the Wolfram Application Server${NORMAL} Azure Setup Manager, version ${CYAN}$version${NORMAL}

EOF
cat <<EOF

  Should any step ${RED}fail${NORMAL} the script shall halt. Completion of each step will be shown in ${GREEN}green${NORMAL}.

  Anytime you can re-run this script with ${CYAN}--help${NORMAL} flag to see available options.

EOF


}
install_msg

SetupFunction()
{
	banner=true
    cd Source/terraform
    GET_CLUSTER_NAME=$(grep -A1 -i cluster-name variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
    GET_CLUSTER_NAME=$(echo $GET_CLUSTER_NAME | tr -d '\r')
    GET_REGION=$(grep -A1 -i aks_region variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
    GET_REGION=$(echo $GET_REGION | tr -d '\r')

	CFILE=~/.azure/azureProfile.json
	if [ -f "$CFILE" ]; then
		TFILE=tenant-id.config
		if [ -f "$TFILE" ]; then
			TENANTID=$(cat tenant-id.config | cut -d '-' -f 5 | head -n1 | cut -d " " -f1)
			TENANTID=$(echo $TENANTID | tr -d '\r')
		else
			echo
			log_error "Cannot find tenant id. Did you enter tenant id ?"
			echo
			exit 1
		fi
	else
		echo
        log_error "Cannot find azure token. Did you run 'az login' ?"
        echo
        exit 1
	fi

	echo
	log_debug "Phase 1 of 5: Prequisites Checks"   
	printf "${YELLOW}☑${CYAN}□□□□${NORMAL} Phase ${YELLOW}1${NORMAL} of ${GREEN}5${NORMAL}: Prequisites Checks\\n"
    run_ok "kubectlFunction" "Checking Kubectl Installed"
    run_ok "terraformFunction" "Checking Terraform Installed"
    run_ok "helmFunction" "Checking Helm Installed"
    run_ok "NEWAKSCHECK" "Checking AKS Status"
    val="yes"
	if [ X"$aks_Exists" = X"$val" ]; then
        echo
        log_error "Cluster already exists."
        echo
        exit 1
    fi

	echo
	log_debug "Phase 2 of 5: Build Azure Kubernetes Cluster (EKS)"
	printf "${GREEN}☑${YELLOW}☑${CYAN}□□□${NORMAL} Phase ${YELLOW}2${NORMAL} of ${GREEN}5${NORMAL}: Build Azure Kubernetes Cluster (AKS)\\n"
	
	CFILE=~/.kube/config
	if [ -f "$CFILE" ]; then
		log_debug "Already has kubeconfig"
		chmod 700 ~/.kube/config
	else
		mkdir -p ~/.kube
		touch ~/.kube/config
		chmod 700 ~/.kube/config
	fi
	
    lower_cluster_name=$(echo $GET_CLUSTER_NAME | tr '[:upper:]' '[:lower:]')
    lower_cluster_name=$(echo $lower_cluster_name | tr -d '\r')
	RESOURCE_GROUP_NAME="$lower_cluster_name-rg-$TENANTID"
    sed -i -e "s~XXXXXX~$RESOURCE_GROUP_NAME~g" main.tf
	
	run_ok "az group create --name $RESOURCE_GROUP_NAME --location $GET_REGION" "Creating Resource Group"
	spsuffix="AzureWAS"
	spuser="$spsuffix$TENANTID"

	while true;
	do
		spoutput=$(az ad sp create-for-rbac --skip-assignment --name=$spuser 2> /dev/null)
		appid=$(echo $spoutput | grep -oP '(?<="appId": ")[^"]*')
		apppassword=$(echo $spoutput | grep -oP '(?<="password": ")[^"]*')
		echo $apppassword >> $LOG_PATH
		if [[ $apppassword =~ "~" ]]; then
			spoutput=$(az ad app credential reset --id $appid --append 2> /dev/null)
			apppassword=$(echo $spoutput | grep -oP '(?<="password": ")[^"]*')
			echo $apppassword >> $LOG_PATH
		elif [[ $apppassword =~ "/" ]]; then
			spoutput=$(az ad app credential reset --id $appid --append 2> /dev/null)
			apppassword=$(echo $spoutput | grep -oP '(?<="password": ")[^"]*')
			echo $apppassword >> $LOG_PATH
		elif [[ $apppassword =~ "\\" ]]; then
			spoutput=$(az ad app credential reset --id $appid --append 2> /dev/null)
			apppassword=$(echo $spoutput | grep -oP '(?<="password": ")[^"]*')
			echo $apppassword >> $LOG_PATH
		else
			echo "password no syntax issues" >> $LOG_PATH
			break;
		fi
	done
	
	
	# find and replace appid and password
    sed -i -e "s~XXXXXX~$appid~g" variables.tf
	sed -i -e "s~YYYYYY~$apppassword~g" variables.tf
	
	spuser=$(echo $spuser | tr '[:upper:]' '[:lower:]')
    spuser=$(echo $spuser | tr -d '\r')
	
    echo "variable \"storage_account_name\" { default = \"$spuser\" } " >> variables.tf
    
    GET_SAN=$(grep -A0 -i storage_account_name variables.tf | grep -i default | awk '{print $6}' | sed -e 's/"//g' | tr -d '\n')
	GET_SAN=$(echo $GET_SAN | tr -d '\r')
	CONTAINER_NAME="tfstate"

	run_ok "createStorageAccount" "Creating Storage Account"
	run_ok "az storage container create --name $CONTAINER_NAME --account-name $GET_SAN --account-key $ACCOUNT_KEY 2> /dev/null" "Creating Terraform Blob Container"
    sed -i -e "s~YYYYYY~$GET_SAN~g" main.tf

    run_ok "terraform init && terraform refresh && terraform plan && terraform apply -auto-approve" "Building AKS - (can take upto 15 minutes)"
    run_ok "az aks get-credentials --resource-group $(terraform output resource_group_name | sed -e 's/"//g') --name $(terraform output kubernetes_cluster_name | sed -e 's/"//g') --overwrite-existing" "Generating kubeconfig configuration"
    cd ..
	
	echo
	log_debug "Phase 3 of 5: Deploy Dependencies"
	printf "${GREEN}☑☑${YELLOW}☑${CYAN}□□${NORMAL} Phase ${YELLOW}3${NORMAL} of ${GREEN}5${NORMAL}: Deploy Dependencies\\n"
	domainsuffix="was"
	azuredomain="$domainsuffix-$TENANTID"
    sed -i -e "s~^    service.beta.kubernetes.io\/azure-dns-label-name: .*~    service.beta.kubernetes.io\/azure-dns-label-name: \"$azuredomain\"~g" ingress-controller/deploy.yml
	run_ok "kubectl apply -f ingress-controller/ & sleep 120" "Setup Ingress Controller"
	run_ok "kubectl apply -f metrics-server/ & sleep 30" "Setup Metrics Server"

	echo
	log_debug "Phase 4 of 5: Wolfram Application Server Deployment"
	printf "${GREEN}☑☑☑${YELLOW}☑${CYAN}□${NORMAL} Phase ${YELLOW}4${NORMAL} of ${GREEN}5${NORMAL}: Wolfram Application Server Deployment\\n"
	run_ok "kubectl apply -f namespace/ && kubectl config set-context --current --namespace=kafka" "Creating Namespace"
	kubectl patch storageclass default -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' >> $LOG_PATH
	run_ok "kubectl apply -f sc/" "Setup Storage Class"
	
	run_ok "kubectl create -f strimzi-kafka-deployment/ && sleep 15 && kubectl wait --for=condition=ready --timeout=30m pod -l name=strimzi-cluster-operator && kubectl create -f kafka && sleep 60 && kubectl wait --for=condition=ready --timeout=30m pod -l statefulset.kubernetes.io/pod-name=kafka-persistent-zookeeper-0 && sleep 60 && kubectl wait --for=condition=ready --timeout=30m pod -l statefulset.kubernetes.io/pod-name=kafka-persistent-kafka-0 &&  sleep 60 && kubectl wait --for=condition=ready --timeout=30m pod -l app.kubernetes.io/name=entity-operator && kubectl create -f kafkabridge && sleep 60 && kubectl wait --for=condition=ready --timeout=30m pod -l app.kubernetes.io/name=kafka-bridge" "Deploying Kafka Cluster (can take upto 10 minutes)"	
	run_ok "kafkaoperatorCheck" "Setting Up Kafka"
	
	run_ok "kubectl config set-context --current --namespace=was" "Set WAS Namespace as default"
		
    run_ok "kubectl apply -f pvc/" "Setup Persistent Volume Claims"
	run_ok "kubectl apply -f services/" "Setup Services"
    
    while true;
    do
        currentregcred=$(kubectl get secret | grep basic-auth | awk '{print $1}')
        if [ X"$currentregcred" = X"basic-auth" ]; then
            log_debug "already basic-auth exists"
            break;
        else
            log_debug "basic-auth doesn't exist"
                run_ok "cd ingress/ && kubectl create secret generic basic-auth --from-file=auth -n was && cd .." "Setup NGINX Auth"
        fi
    done
	run_ok "kubectl apply -f ingress/" "Setup Ingress"
    
	
    # Minio deployment setup
    CURRENT_MINIO_ACCESS_KEY=$(grep -A1 -i MINIO_ACCESS_KEY deployments/minio-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIO_ACCESS_KEY"'~'"$GET_SAN"'~g' deployments/minio-deployment.yaml
    CURRENT_MINIO_SECRET_KEY=$(grep -A1 -i MINIO_SECRET_KEY deployments/minio-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIO_SECRET_KEY"'~'"$ACCOUNT_KEY"'~g' deployments/minio-deployment.yaml
    
	# Resource Manger deployment setup
    CURRENT_MINIOACCESSKEY=$(grep -A1 -i MINIOACCESSKEY deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIOACCESSKEY"'~'"$GET_SAN"'~g' deployments/resource-manager-deployment.yaml
    CURRENT_MINIOSECRETKEY=$(grep -A1 -i MINIOSECRETKEY deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
	sed -i -e 's~'"$CURRENT_MINIOSECRETKEY"'~'"$ACCOUNT_KEY"'~g' deployments/resource-manager-deployment.yaml
    resources_bucket_name="was-resources-$TENANTID"
    nodefiles_bucket_name="was-nodefiles-$TENANTID"
    CURRENT_RESOURCEINFOBUCKET=$(grep -A1 -i RESOURCEINFO.BUCKET deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_RESOURCEINFOBUCKET"'~'"$resources_bucket_name"'~g' deployments/resource-manager-deployment.yaml
    CURRENT_NODEFILESBUCKET=$(grep -A1 -i NODEFILES.BUCKET deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_NODEFILESBUCKET"'~'"$nodefiles_bucket_name"'~g' deployments/resource-manager-deployment.yaml
    
	# AWES deployment setup
	domainsuf="cloudapp.azure.com"
	fullazuredomain="$azuredomain.$GET_REGION.$domainsuf"
	rm -rf ingress-controller/domain.config
	echo $fullazuredomain >> ingress-controller/domain.config
	sed -i -e "s/domain.com/$fullazuredomain/g" deployments/active-web-elements-server-deployment.yaml
	
	run_ok "kubectl apply -f deployments/" "Setup Deployments"
	run_ok "deploymentStatus" "Waiting for Deployments To Be Ready"
	run_ok "endpointStatus" "Checking Base URL Accessible"
	
	cd custom-metrics/
	run_ok "custommetricsSetup" "Setup Custom Metrics"
	cd ..
	run_ok "kubectl config set-context --current --namespace=was && kubectl apply -f hpa/" "Setup Horizontal Pod Autoscaler"

	
	echo
	log_debug "Phase 5 of 5: Application URL Details"
	printf "${GREEN}☑☑☑☑${YELLOW}☑${NORMAL} Phase ${YELLOW}5${NORMAL} of ${GREEN}5${NORMAL}: Application URL Details\\n\n"
    BASE_URL="$fullazuredomain"
    printf "${GREEN}Base URL - Active Web Elements Server:${NORMAL} http://$BASE_URL/\n\n"
    printf "${GREEN}Resource Manager:${NORMAL} http://$BASE_URL/resources/\n\n"
    printf "${GREEN}Endpoints Manager:${NORMAL} http://$BASE_URL/endpoints/\n\n"
    printf "${GREEN}Nodefiles:${NORMAL} http://$BASE_URL/nodefiles/\n\n"
    printf "${GREEN}Endpoints Info:${NORMAL} http://$BASE_URL/.applicationserver/info\n\n"
    printf "${GREEN}Restart AWES:${NORMAL} http://$BASE_URL/.applicationserver/kernel/restart\n\n"
    
	echo
    echo "AKS Cluster build complete and Wolfram Application Server Deployed. Our warmest appreciation to you for running Wolfram Application Server on Azure environment. Enjoy!"
	echo

}

createStorageAccount()
{
	san=$(az storage account create --resource-group $RESOURCE_GROUP_NAME --name $GET_SAN --sku Standard_LRS --encryption-services blob 2> /dev/null)
	ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $GET_SAN --query '[0].value' -o tsv  2> /dev/null)
}

custommetricsSetup()
{
	kubectl config set-context --current --namespace=monitoring >> $LOG_PATH
	kubectl apply -f prometheus.yaml >> $LOG_PATH
	sleep 15
	kubectl wait --for=condition=ready --timeout=30m pod -l app=prometheus-server -n monitoring >> $LOG_PATH
	helm repo add prometheus-community https://prometheus-community.github.io/helm-charts  >> $LOG_PATH
	helm repo update >> $LOG_PATH
	helm install was -f values.yaml prometheus-community/prometheus-adapter --namespace monitoring >> $LOG_PATH
	sleep 15
	kubectl wait --for=condition=ready --timeout=30m pod -l app=prometheus-adapter -n monitoring >> $LOG_PATH
}


deploymentStatus()
{
    while true;
    do
        currentawesStatus=$(kubectl get pods --field-selector=status.phase=Running -n was | grep -i "active-web-elements-server-deployment-" | awk '{print $2}' | head -qn1)
        if [ X"$currentawesStatus" = X"1/1" ]; then
            log_debug "awes ready"
            break;
        else
            log_debug "awes not ready"
            sleep 5;
        fi
    done

}

endpointStatus()
{
    BASE_URL="$fullazuredomain"
    while true;
    do
        currentendpointStatus=$(curl -s -o /dev/null -I -w "%{http_code}" http://$BASE_URL/)
        if [ X"$currentendpointStatus" = X"503" ]; then
            log_debug "endpoint accessible"
            break;
        else
            log_debug "endpoint not accessible yet"
            sleep 5;
        fi
    done

}

kafkaoperatorCheck()
{
    while true;
    do
        currentKafkaoperatorStatus=$(kubectl get pods --field-selector=status.phase=Running -n kafka | grep -i "kafka-persistent-entity-operator-" | awk '{print $2}')
        if [ X"$currentKafkaoperatorStatus" = X"3/3" ]; then
            log_debug "kafka operator ready"
            break;
        else
            log_debug "kafka operator not ready"
            sleep 5;
        fi
    done
}

terraformFunction()
{
    while true; do
      if [ -x "/usr/local/bin/terraform" ]; then
        break
      elif [ -x "/usr/bin/terraform" ]; then
        break
      else
        printf "${RED}Terraform not installed. Cannot continue.${NORMAL}\\n"
        exit 1
      fi
    done

}

helmFunction()
{
    while true; do
      if [ -x "/usr/local/bin/helm" ]; then
        break
      elif [ -x "/usr/bin/helm" ]; then
        break
      else
        printf "${RED}Helm not installed. Cannot continue.${NORMAL}\\n"
        exit 1
      fi
    done

}

kubectlFunction()
{
    while true; do
      if [ -x "/usr/local/bin/kubectl" ]; then
        break
      elif [ -x "/usr/bin/kubectl" ]; then
        break
      else
        printf "${RED}Kubectl not installed. Cannot continue.${NORMAL}\\n"
        exit 1
      fi
    done

}

kafkaShutdown()
{
    kubectl delete --ignore-not-found=true -f kafkabridge/ >> $LOG_PATH
    kubectl delete --ignore-not-found=true -f kafka/ >> $LOG_PATH
    sleep 60
    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-kafka-0" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "kafka 0 not running"
            break;
        else
            log_debug "kafka 0 forcing shutdown"
            kubectl delete pod kafka-persistent-kafka-0 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done
    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-kafka-1" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "kafka 1 not running"
            break;
        else
            log_debug "kafka 1 forcing shutdown"
            kubectl delete pod kafka-persistent-kafka-1 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done
    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-kafka-2" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "kafka 2 not running"
            break;
        else
            log_debug "kafka 2 forcing shutdown"
            kubectl delete pod kafka-persistent-kafka-2 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done
    
    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-zookeeper-0" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "zookeeper 0 not running"
            break;
        else
            log_debug "zookeeper 0 forcing shutdown"
            kubectl delete pod kafka-persistent-zookeeper-0 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done

    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-zookeeper-1" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "zookeeper 1 not running"
            break;
        else
            log_debug "zookeeper 1 forcing shutdown"
            kubectl delete pod kafka-persistent-zookeeper-1 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done
    
    while true;
    do
        current=$(kubectl get pods -n kafka | grep -i "kafka-persistent-zookeeper-2" | awk '{print $1}' | head -qn1)
        if [ -z $current ]; then
            log_debug "zookeeper 2 not running"
            break;
        else
            log_debug "zookeeper 2 forcing shutdown"
            kubectl delete pod kafka-persistent-zookeeper-2 -n kafka --grace-period=0 --force 2>/dev/null 2>&1
        fi
    done

}

deleteSP()
{
	id=$(az ad sp list --output table --all | grep $spuser | awk '{print $3}') && az ad sp delete --id $id
}

DeleteFunction()
{
	banner=true
	cd Source/terraform
    GET_CLUSTER_NAME=$(grep -A1 -i cluster-name variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
    GET_CLUSTER_NAME=$(echo $GET_CLUSTER_NAME | tr -d '\r')
    GET_REGION=$(grep -A1 -i aks_region variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
    GET_REGION=$(echo $GET_REGION | tr -d '\r')
	cd ..
	
	echo
	log_debug "Phase 1 of 5: Prequisites Checks"   
	printf "${YELLOW}☑${CYAN}□□□□${NORMAL} Phase ${YELLOW}1${NORMAL} of ${GREEN}5${NORMAL}: Prequisites Checks\\n"
    run_ok "kubectlFunction" "Checking Kubectl Installed"
    run_ok "terraformFunction" "Checking Terraform Installed"
    run_ok "helmFunction" "Checking Helm Installed"
    run_ok "CURRENTAKSCHECK" "Checking AKS Status"
	
    val="no"
	if [ X"$aks_Exists" = X"$val" ]; then
        echo
        log_error "Trying to delete Cluster when it doesn't exist. What are you trying to do?"
        echo
        exit 1
    fi
    
	echo
	log_debug "Phase 2 of 5: Delete Wolfram Application Server Deployments"
	printf "${GREEN}☑${YELLOW}☑${CYAN}□□□${NORMAL} Phase ${YELLOW}2${NORMAL} of ${GREEN}5${NORMAL}: Delete Wolfram Application Server Deployments\\n"
	run_ok "kubectl delete --ignore-not-found=true -f deployments/" "Deleting Deployments"
    run_ok "kafkaShutdown" "Deleting Kafka Cluster"
    run_ok "kubectl delete secret generic basic-auth --ignore-not-found=true" "Deleting NGINX Auth"
    
	run_ok "kubectl delete --ignore-not-found=true -f ingress/" "Deleting Ingress"
	run_ok "kubectl delete --ignore-not-found=true -f hpa/" "Deleting Horizontal Pod Autoscaler"
    run_ok "kubectl delete --ignore-not-found=true -f services/" "Deleting Services"
	run_ok "kubectl delete --ignore-not-found=true -f pvc/" "Deleting Persistent Volume Claims"

	run_ok "kubectl delete --ignore-not-found=true -f strimzi-kafka-deployment/020-RoleBinding-strimzi-cluster-operator.yaml -n kafkacluster && kubectl delete --ignore-not-found=true -f strimzi-kafka-deployment/032-RoleBinding-strimzi-cluster-operator-topic-operator-delegation.yaml -n kafkacluster && kubectl delete --ignore-not-found=true -f strimzi-kafka-deployment/031-RoleBinding-strimzi-cluster-operator-entity-operator-delegation.yaml -n kafkacluster && kubectl delete --ignore-not-found=true -f strimzi-kafka-deployment/ -n kafka && kubectl delete --ignore-not-found=true -f kafka && kubectl delete --ignore-not-found=true -f kafkabridge" "Deleting Kafka Cluster Operator"
    run_ok "kubectl delete --ignore-not-found=true apiservice v1beta1.custom.metrics.k8s.io && kubectl delete --ignore-not-found=true -f namespace/" "Deleting WAS Namespace"
	run_ok "kubectl config set-context --current --namespace=default" "Reset Namespace"
    
	echo
	log_debug "Phase 3 of 5: Delete Dependencies"
	printf "${GREEN}☑☑${YELLOW}☑${CYAN}□□${NORMAL} Phase ${YELLOW}3${NORMAL} of ${GREEN}5${NORMAL}: Delete Dependencies\\n"
	run_ok "kubectl delete --ignore-not-found=true -f metrics-server/" "Deleting Metrics Server"
	run_ok "kubectl delete --ignore-not-found=true -f ingress-controller/" "Deleting Ingress Controller"

	echo
	log_debug "Phase 4 of 5: Delete Azure Kubernetes Cluster (AKS)"
	printf "${GREEN}☑☑☑${YELLOW}☑${CYAN}□${NORMAL} Phase ${YELLOW}4${NORMAL} of ${GREEN}5${NORMAL}: Delete Azure Kubernetes Cluster (AKS)\\n"
    cd terraform
	run_ok "sleep 5 && terraform init && terraform refresh && terraform destroy -auto-approve" "Deleting AKS"
	cd ..
	
	echo
	log_debug "Phase 5 of 5: Cleanup"
	printf "${GREEN}☑☑☑☑${YELLOW}☑${NORMAL} Phase ${YELLOW}5${NORMAL} of ${GREEN}5${NORMAL}: Cleanup\\n"
	

	BASE_URL=$(cat ingress-controller/domain.config | tr -d '\n' )
	sed -i -e "s~$BASE_URL~domain.com~g" deployments/active-web-elements-server-deployment.yaml
	rm -rf ingress-controller/domain.config
	
	sed -i -e "s~^    service.beta.kubernetes.io\/azure-dns-label-name: .*~    service.beta.kubernetes.io\/azure-dns-label-name: \"domain\"~g" ingress-controller/deploy.yml


    # Reset deployment setup
    CURRENT_MINIO_ACCESS_KEY=$(grep -A1 -i MINIO_ACCESS_KEY deployments/minio-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIO_ACCESS_KEY"'~<your-access-key>~g' deployments/minio-deployment.yaml
    CURRENT_MINIO_SECRET_KEY=$(grep -A1 -i MINIO_SECRET_KEY deployments/minio-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIO_SECRET_KEY"'~<your-secret-key>~g' deployments/minio-deployment.yaml
    CURRENT_MINIOACCESSKEY=$(grep -A1 -i MINIOACCESSKEY deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIOACCESSKEY"'~<your-access-key>~g' deployments/resource-manager-deployment.yaml
    CURRENT_MINIOSECRETKEY=$(grep -A1 -i MINIOSECRETKEY deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_MINIOSECRETKEY"'~<your-secret-key>~g' deployments/resource-manager-deployment.yaml
    CURRENT_RESOURCEINFOBUCKET=$(grep -A1 -i RESOURCEINFO.BUCKET deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_RESOURCEINFOBUCKET"'~<your-resourceinfo-bucketname>~g' deployments/resource-manager-deployment.yaml
    CURRENT_NODEFILESBUCKET=$(grep -A1 -i NODEFILES.BUCKET deployments/resource-manager-deployment.yaml | grep -i value: |  awk '{print $2}')
    sed -i -e 's~'"$CURRENT_NODEFILESBUCKET"'~<your-nodefiles-bucketname>~g' deployments/resource-manager-deployment.yaml
    
	# delete storage account
	cd terraform
    GET_SAN=$(grep -A0 -i storage_account_name variables.tf | grep -i default | awk '{print $6}' | sed -e 's/"//g' | tr -d '\n')
	GET_SAN=$(echo $GET_SAN | tr -d '\r')
	TENANTID=$(az account list --query [].tenantId --output tsv | cut -d '-' -f 5)
	TENANTID=$(echo $TENANTID | tr -d '\r')
	lower_cluster_name=$(echo $GET_CLUSTER_NAME | tr '[:upper:]' '[:lower:]')
    lower_cluster_name=$(echo $lower_cluster_name | tr -d '\r')
	spsuffix="AzureWAS"
	spuser="$spsuffix$TENANTID"
	RESOURCE_GROUP_NAME="$lower_cluster_name-rg-$TENANTID"
	run_ok "az storage account delete --name $GET_SAN --resource-group $RESOURCE_GROUP_NAME --yes" "Deleting Storage Account"
	
	# delete service prinipal account
	run_ok "deleteSP" "Deleting Service Principal Account"
	
	set -e
	# delete resource groups
	run_ok "az group delete --name $RESOURCE_GROUP_NAME --no-wait --yes && az group delete --name NetworkWatcherRG --no-wait --yes" "Deleting Resource Group"
	run_ok "az group delete --name WAS-rg --no-wait --yes || true" "Deleting WAS Resource Group"
	set +e
	# Cleanup
	rm -rf tmpfile
	awk '!/storage_account_name/' variables.tf  > tmpfile && mv tmpfile variables.tf >> $LOG_PATH
	# Reset main.tf values to default
	sed -i -e 's/'"$RESOURCE_GROUP_NAME"'/XXXXXX/g' main.tf
	sed -i -e 's/'"$GET_SAN"'/YYYYYY/g' main.tf

	# variables
	# find and replace appid and password
	GET_APP_ID=$(grep -A2 -i appId variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
	GET_APP_ID=$(echo $GET_APP_ID | tr -d '\r')
    sed -i -e 's~'"$GET_APP_ID"'~XXXXXX~g' variables.tf
	
	GET_APP_PASSWORD=$(grep -A2 -i password variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
	GET_APP_PASSWORD=$(echo $GET_APP_PASSWORD | tr -d '\r')
	sed -i -e 's~'"$GET_APP_PASSWORD"'~YYYYYY~g' variables.tf
	rm -rf tenant-id.config
	rm -rf .terraform*
	rm -rf stopspinning*
	cd ..
	rm -rf stopspinning
    rm -rf efs/mountIDs.txt
    rm -rf efs/stopspinning
    rm -rf custom-metrics/stopspinning
	rm -rf tmpfile	
	cd ..
	
	echo
    echo "Deleted AKS Cluster and Wolfram Application Server. Our warmest appreciation to you for running Wolfram Application Server on Azure environment. Thank You!"
	echo
    
}

NEWAKSCHECK()
{
	suffix="-aks"
	CLUSTER="$GET_CLUSTER_NAME$suffix"
    clusterExists=$(az aks list | grep $CLUSTER 2>/dev/null 2>&1 )
	if [[ $clusterExists =~ $CLUSTER ]]; then
		printf "cluster found"
		aks_Exists="yes"
	else
	    printf "no cluster found" 2>/dev/null 2>&1
		aks_Exists="no"
	fi
}

CURRENTAKSCHECK()
{
    cd terraform
    GET_CLUSTER_NAME=$(grep -A1 -i cluster-name variables.tf | grep -i default | awk '{print $3}' | sed -e 's/"//g' | tr -d '\n')
    GET_CLUSTER_NAME=$(echo $GET_CLUSTER_NAME | tr -d '\r')
	suffix="-aks"
	CLUSTER="$GET_CLUSTER_NAME$suffix"
    clusterExists=$(az aks list | grep $CLUSTER 2>/dev/null 2>&1 )
	if [[ $clusterExists =~ $CLUSTER ]]; then
		printf "cluster found"
		aks_Exists="yes"
	else
	    printf "no cluster found" 2>/dev/null 2>&1
		aks_Exists="no"
	fi
    cd ..
}

URLFunction()
{
    banner=true
	cd /Source
    BASE_URL=$(cat ingress-controller/domain.config | tr -d '\n' )
	echo
	log_debug "Phase 1 of 1: Application URL Details"
	printf "${GREEN}${YELLOW}☑${CYAN}${NORMAL} Phase ${YELLOW}1${NORMAL} of ${GREEN}1${NORMAL}: Application URL Details\\n\n"
    printf "${GREEN}Base URL - Active Web Elements Server:${NORMAL} http://$BASE_URL/\n\n"
    printf "${GREEN}Resource Manager:${NORMAL} http://$BASE_URL/resources/\n\n"
    printf "${GREEN}Endpoints Manager:${NORMAL} http://$BASE_URL/endpoints/\n\n"
    printf "${GREEN}Nodefiles:${NORMAL} http://$BASE_URL/nodefiles/\n\n"
    printf "${GREEN}Endpoints Info:${NORMAL} http://$BASE_URL/.applicationserver/info\n\n"
    printf "${GREEN}Restart AWES:${NORMAL} http://$BASE_URL/.applicationserver/kernel/restart\n\n"
	
}


helpFunction()
{
  banner=true
  printf "Usage: %s %s [options]\\n" "${CYAN}" $(basename "$0")
  echo
  printf "  ${YELLOW}--create${NORMAL} \t\t- Setup EKS and Deploy Wolfram Application Server on AWS\\n"
  printf "  ${YELLOW}--delete${NORMAL} \t\t- Delete EKS and Wolfram Application Server from AWS\\n"
  printf "  ${YELLOW}--endpoint-info${NORMAL} \t- Get Your Application URL Endpoints Information\\n"
  printf "  ${YELLOW}--help${NORMAL} \t\t- Help\\n"
  echo
}


invalidoptionsFunction()
{
    log_error "Invalid flags given."
	echo
	helpFunction
    exit 1
}

while test $# -gt 0
do
    case "$1" in
        --create) SetupFunction
            ;;
        --delete) DeleteFunction
            ;;
        --endpoint-info) URLFunction
            ;;
        --help) helpFunction
            ;;
        --*) invalidoptionsFunction
            ;;
        *) invalidoptionsFunction
            ;;
    esac
    shift
done

if [ "$banner" = false ] ; then
    log_error "Missing required flags."
	echo
	helpFunction
    exit 1
fi

exit 0
